from PyQt4 import QtCore, QtGui
from guiqwt.builder import make
import sys
import serial

from collections import deque 

import UI
import numpy
import pickle
import SimpleTimeDomainView
from UI.MainWindow import Ui_MainWindow
import LogProbe

from UI.CalDiag import Ui_CalDiag
from UI.ProbeCalibrateDiag import Ui_ProbeCalibrateDiag
from UI.SelectProbesDiag import Ui_SelectProbesDiag
from UI.SimplePlotDiag import Ui_SimplePlotDiag
from UI.ConnectDiag import Ui_ConnectDiag
import CommsMonitor


import threading



class SimplePlot(QtGui.QDialog, Ui_SimplePlotDiag):
    def __init__(self, ProbeCal, Buffer, Enables, Averaged):
        QtGui.QDialog.__init__(self)
        self.setupUi(self)
        
        self.curvewidget.register_all_curve_tools()
        self.curvewidget.plot.set_plot_limits(0,10000,0,100) 
        
        self.Buffer = Buffer
        self.ProbeCal = ProbeCal
        self.Timer = QtCore.QTimer()
        self.Timer.setInterval(1000) 
        self.Timer.setSingleShot(False)
        QtCore.QObject.connect(self.Timer, QtCore.SIGNAL("timeout()"), self.Tick)
        self.Timer.start()
        
        
        
        self.DataBuffers = {}
        self.Plots = {}
        i = 0
        while i < len(Enables):
            if Enables[i] == True:
                self.DataBuffers[i] = deque([],10000)
                self.Plots[i] = make.curve([], [], color='b')
                self.curvewidget.plot.add_item(self.Plots[i])
        
            i+=1        
        
    def Tick(self):
        t = numpy.arange(0,10000)
        for probe in self.DataBuffers.keys():
            self.DataBuffers[probe].append(self.ProbeCal[probe].GetTemp(self.Buffer[probe]))
            self.Plots[probe].set_data(t, self.DataBuffers[probe])
            self.Plots[probe].plot().replot()
        
        
        


class SelectProbes(QtGui.QDialog, Ui_SelectProbesDiag):
    def __init__(self, ProbeCalObj):
        QtGui.QDialog.__init__(self)
        self.setupUi(self)
        

class CalObj:
    def __init__(self, ProbeName, Log = True):
        self.ProbeName = ProbeName
        self.VoltgageDividerRes = 10000.0
        self.RefVoltage = 5.0
        #if Log:
        self.SteinhartHart = LogProbe.SteinhartHart()
    
    def GetV(self, RawData):
        return (RawData*1.0*self.RefVoltage)/1024.0
    
    def GetRes(self, RawData):
        V = self.GetV(RawData)
        return V*self.VoltgageDividerRes/(self.RefVoltage - V)
        
    def SetPoint(self, Temp, Value, Point):
        
        Res = self.GetRes(Value)
        self.SteinhartHart.SetCalibrationPoint(Temp, Res, Point)
        
    def Update(self):
        self.SteinhartHart.Calibrate()
        
    def GetTemp(self, RawData):
        Res = self.GetRes(RawData)
        return self.SteinhartHart.GetTemp(Res)
        
    def GetCalPoints(self):
        return self.SteinhartHart.GetCalPoints()

class Cal(QtGui.QDialog, Ui_CalDiag):
    def __init__(self, ProbeCalObj):
        QtGui.QDialog.__init__(self)
        self.setupUi(self)
        
        self.curvewidget.register_all_curve_tools()
        self.curve_item = make.curve([], [], color='b')
        self.curvewidget.plot.add_item(self.curve_item)
        #self.curvewidget.plot.set_plot_limits(0,1024,-30,150) 
        
        self.ProbeCalObj = ProbeCalObj
        self.ProbeNameEdit.setText(self.ProbeCalObj.ProbeName)
        CalPoints = self.ProbeCalObj.GetCalPoints()
        self.lineEdit.setText("""%0.2f C"""%CalPoints[0][0])
        self.lineEdit_2.setText("""%d """%CalPoints[0][1])
        self.lineEdit_3.setText("""%0.2f C"""%CalPoints[1][0])
        self.lineEdit_4.setText("""%d """%CalPoints[1][1])
        self.lineEdit_5.setText("""%0.2f C"""%CalPoints[2][0])
        self.lineEdit_6.setText("""%d """%CalPoints[2][1])
        
        self.connect(self.ProbeNameEdit, QtCore.SIGNAL("editingFinished()"), self.UpdateName)
        
        self.connect(self.lineEdit, QtCore.SIGNAL("editingFinished()"), self.UpdateTemp1)
        
        self.connect(self.pushButton, QtCore.SIGNAL("clicked()"), self.UpdateSample1)
        self.connect(self.pushButton_2, QtCore.SIGNAL("clicked()"), self.UpdateSample2)
        self.connect(self.pushButton_3, QtCore.SIGNAL("clicked()"), self.UpdateSample3)
        
        self.DrawGraph()
        
        
    def UpdateName(self):
        self.ProbeCalObj.ProbeName = self.ProbeNameEdit.text()
    
    def UpdateTemp1(self):
        pass
        
    def UpdateSample1(self):
        pass
        Raw1 = int(self.lineEdit_2.text())
        Temp1 = float(self.lineEdit.text().replace("C",""))
        self.ProbeCalObj.SetPoint(Temp1, Raw1, 0)
        self.DrawGraph()
    
    def UpdateSample2(self):
        pass
        Raw2 = int(self.lineEdit_4.text())
        Temp2 = float(self.lineEdit_3.text().replace("C",""))
        self.ProbeCalObj.SetPoint(Temp2, Raw2, 1)
        self.DrawGraph()
    
    def UpdateSample3(self):
        pass
        Raw3 = int(self.lineEdit_6.text())
        Temp3 = float(self.lineEdit_5.text().replace("C",""))
        self.ProbeCalObj.SetPoint(Temp3, Raw3, 2)
        self.DrawGraph()
        #
        #
    def DrawGraph(self):
        RawSamples = numpy.arange(0,1024)
        Temps = []
        i = 1
        while i < len(RawSamples):
            Temp = self.ProbeCalObj.GetTemp(RawSamples[i])
            Temps.append(Temp)
            i += 1
        
            
        #Grad = (1.0 * (self.ProbeCalObj.Temp1 - self.ProbeCalObj.Temp2)) / ((1.0* self.ProbeCalObj.Raw1) - (1.0*self.ProbeCalObj.Raw2))
        #Offset = ((1.0 * self.ProbeCalObj.Temp1 * self.ProbeCalObj.Raw2)-(1.0 * self.ProbeCalObj.Temp2 * self.ProbeCalObj.Raw1))/(1.0*self.ProbeCalObj.Raw2 - 1.0*self.ProbeCalObj.Raw1)
        #Data = (RawSamples * self.ProbeCalObj.Grad) + self.ProbeCalObj.Offset
        self.curve_item.set_data(RawSamples[1:], numpy.array(Temps))
        self.curve_item.plot().replot()
        

class CalibrateProbes(QtGui.QDialog, Ui_ProbeCalibrateDiag):
    def __init__(self, Buffer, ProbeCal):
        QtGui.QDialog.__init__(self)
        self.setupUi(self)
        
        self.Buffer = Buffer
        self.ProbeCal = ProbeCal
        self.Timer = QtCore.QTimer()
        self.Timer.setInterval(1000) 
        self.Timer.setSingleShot(False)
        QtCore.QObject.connect(self.Timer, QtCore.SIGNAL("timeout()"), self.Tick)
        self.Timer.start()
    
    def Tick(self):
        i = 0
        while i < len(self.Buffer):
            Data = self.Buffer[i]
            self.tableWidget.setItem(i, 0, QtGui.QTableWidgetItem("""%s"""%(self.ProbeCal[i].ProbeName)))
            self.tableWidget.setItem(i, 1, QtGui.QTableWidgetItem("""%.2f"""%(Data)))
            self.tableWidget.setItem(i, 2, QtGui.QTableWidgetItem("""%.2f"""%(self.ProbeCal[i].GetV(Data))))
            self.tableWidget.setItem(i, 3, QtGui.QTableWidgetItem("""%.2f"""%(self.ProbeCal[i].GetRes(Data))))
            self.tableWidget.setItem(i, 4, QtGui.QTableWidgetItem("""%.2f"""%(self.ProbeCal[i].GetTemp(Data))))
            #self.tableWidget.setItem(i, 2, QtGui.QTableWidgetItem("""%.2f"""%(self.ProbeCal[i].GetTemp(Data))))
            
            self.tableWidget.setCellWidget(i, 5, QtGui.QPushButton("Calibrate"))
            self.tableWidget.cellWidget(i, 5).uniqueId = """%d"""%i
            self.tableWidget.cellWidget(i, 5).clicked.connect(self.Calibrate)
            i = i + 1
    
    def Calibrate(self):
        self.CalDiag = Cal(self.ProbeCal[int(self.sender().uniqueId)])
        self.CalDiag.show()
        #int(self.sender().uniqueId)
        #self.ProbeCal[int(self.sender().uniqueId)] = 100

class ConnectDiag(QtGui.QDialog, Ui_ConnectDiag):
    def __init__(self):
        QtGui.QDialog.__init__(self)
        self.setupUi(self)
    
    def GetComPort(self):
        return self.comboBox.currentText()
        
    def GetBaud(self):
        return self.comboBox_2.currentText()

class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)    
        self.setupUi(self)
        self.PlotViews = []
        
        self.Buffer = [0,128,512,0,0,0]
        self.ProbeCal = []
        try:
            f = open("CalFile.dat","rb")
            while 1:
                try:
                    self.ProbeCal.append(pickle.load(f))
                except:
                    break
                    
            f.close()
        except:
            self.ProbeCal = [CalObj('1'), CalObj('2'), CalObj('3'), CalObj('4'), CalObj('5'), CalObj('6')]
        
        self.connect(self.actionCalibrate_Probes, QtCore.SIGNAL("triggered()"), self.CalibrateProbes)
        self.connect(self.actionConnect, QtCore.SIGNAL("triggered()"), self.Connect1)
        self.connect(self.actionDisconnect, QtCore.SIGNAL("triggered()"), self.Disconnect)
        
        self.connect(self.pushButton_2, QtCore.SIGNAL("clicked()"), self.ToggleOutput)
        #self.connect(self.pushButton_3, QtCore.SIGNAL("clicked()"), self.Close)
        self.connect(self.pushButton, QtCore.SIGNAL("clicked()"), self.SelectProbesAction)
        
        self.CommsStatus = CommsMonitor.Status()
        self.CommsStatus.Run = True
        
        self.Output = [114]
        self.commsthread = None

        
        self.SimplePlotViews = []
        
    def Connect1(self):
        print "connect"
        self.ConnectDiag = ConnectDiag()
        self.connect(self.ConnectDiag, QtCore.SIGNAL("accepted()"), self.Connect2)
        self.ConnectDiag.show()
    
    def Connect2(self):
        Port = self.ConnectDiag.GetComPort()
        Baud = int(self.ConnectDiag.GetBaud())
        
        if self.commsthread == None:
            self.SerialObj = serial.Serial(str(Port), 2400)
            self.SerialObj.setStopbits(2)
            self.SerialObj.setTimeout(2)
        
            self.commsthread = threading.Thread(target = CommsMonitor.GetData, args = (self.Buffer, self.CommsStatus, self.SerialObj))
            self.commsthread.start()
        else:
            print "Comms Thread already running"
        
    def Disconnect(self):
        self.CommsStatus.Run = False
        while self.commsthread.isAlive():
            pass
        print "Comms monitor closed"
        self.commsthread = None
        
    
    def closeEvent(self, Event):
        f = open("CalFile.dat","wb")
        for Cal in self.ProbeCal:
            pickle.dump(Cal, f)
        f.close()
        
        print "Exiting"
        self.CommsStatus.Run = False
        
    
    def ToggleOutput(self):
        if self.Output == 133:
            self.Output = 114
            self.SerialObj.write(chr(self.Output))
        else:
            self.Output = 133
            self.SerialObj.write(chr(self.Output))
        print self.Output
    
    def CalibrateProbes(self):
        self.CalibrateDiag = CalibrateProbes(self.Buffer, self.ProbeCal)
        self.CalibrateDiag.show()
        
    def SelectProbesAction(self):
        self.GetProbesDiag = SelectProbes(self.ProbeCal)
        self.GetProbesDiag.show()
        self.connect(self.GetProbesDiag, QtCore.SIGNAL("accepted()"), self.OpenSimplePlotView)
        
    def OpenSimplePlotView(self):
        ProbeStates = [False, False, False, False,False, False]
        ProbeStates[0] = (2==self.GetProbesDiag.checkBox_1.checkState())
        ProbeStates[1] = (2==self.GetProbesDiag.checkBox_2.checkState())
        ProbeStates[2] = (2==self.GetProbesDiag.checkBox_3.checkState())
        ProbeStates[3] = (2==self.GetProbesDiag.checkBox_4.checkState())
        ProbeStates[4] = (2==self.GetProbesDiag.checkBox_5.checkState())
        ProbeStates[5] = (2==self.GetProbesDiag.checkBox_6.checkState())
        Averaged = (2==self.GetProbesDiag.checkBox_7.checkState())
        Diag = SimplePlot(self.ProbeCal, self.Buffer, ProbeStates, Averaged)
        Diag.show()
        self.SimplePlotViews.append(Diag)
    



app = QtGui.QApplication(sys.argv)
form = MainWindow()
form.show()
app.exec_()